#include "../../src/ffterm.h"

#include <windows.h>

static void w32_platformInit(void) {
	HANDLE hConsole;

	hConsole = GetStdHandle(STD_INPUT_HANDLE);

	SetConsoleMode(hConsole, 1);
}

static int w32_fgetc(FILE *f) {
	INPUT_RECORD input;
	DWORD read;
	ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &input, 1, &read);
	
	if(input.EventType == KEY_EVENT) {
		if(input.Event.KeyEvent.bKeyDown) {
			return (char) input.Event.KeyEvent.uChar.AsciiChar;
		}
	}
	
	return -1;
}


static FF_T_UINT64 w32_getTicks() {
	LARGE_INTEGER ticks;
	QueryPerformanceCounter(&ticks);

	return (FF_T_UINT64) ticks.QuadPart;//timeGetTime();
}

static FF_T_UINT64 w32_getTickRate() {
	LARGE_INTEGER freq;
	QueryPerformanceFrequency(&freq);
	//MMRESULT res = timeBeginPeriod(1);
	return (FF_T_UINT64) freq.QuadPart;
}

static FF_T_UINT32 w32_getConsoleWidth() {
	CONSOLE_SCREEN_BUFFER_INFO	consoleInfo;
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

	GetConsoleScreenBufferInfo(hConsole, &consoleInfo);

	return consoleInfo.srWindow.Right + 1;
}

static FF_T_UINT32 w32_getConsoleHeight() {
	CONSOLE_SCREEN_BUFFER_INFO	consoleInfo;
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

	GetConsoleScreenBufferInfo(hConsole, &consoleInfo);

	return consoleInfo.srWindow.Bottom + 1;
}

static void w32_setConsoleColour(FF_T_UINT16 Colour) {
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	WORD wAttributes = 0x0000;

	if(Colour & FFT_FOREGROUND_RED) {
		wAttributes |= FOREGROUND_RED;
	}

	if(Colour & FFT_FOREGROUND_GREEN) {
		wAttributes |= FOREGROUND_GREEN;
	}

	if(Colour & FFT_FOREGROUND_BLUE) {
		wAttributes |= FOREGROUND_BLUE;
	}

	if(Colour & FFT_FOREGROUND_INTENSITY) {
		wAttributes |= FOREGROUND_INTENSITY;
	}

	if(Colour & FFT_BACKGROUND_RED) {
		wAttributes |= BACKGROUND_RED;
	}

	if(Colour & FFT_BACKGROUND_GREEN) {
		wAttributes |= BACKGROUND_GREEN;
	}

	if(Colour & FFT_BACKGROUND_BLUE) {
		wAttributes |= BACKGROUND_BLUE;
	}

	if(Colour & FFT_BACKGROUND_INTENSITY) {
		wAttributes |= BACKGROUND_INTENSITY;
	}
	
	if(hConsole) {
		SetConsoleTextAttribute(hConsole, wAttributes);
	}
}

static void w32_createBgThread(FFT_THREADROUTINE pfnRoutine, void *pParam) {
	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) pfnRoutine, pParam, 0, NULL);
}

static const FFT_CUSTOMPARAMS g_oPlatformParams = {
	0x0D,					///< Return charachter.
	0x08,					///< Backspace charachter.
	0x09,					///< Tab character.
	0x1B,					///< ESC char.
	"\n",					///< CRLF string.
	FFT_ENABLE_ECHO_INPUT,	///< Default mode.
};

static const FFT_PLATFORMSPEC g_oPlatformSpecification = {
	&g_oPlatformParams,		///< FFT_CUSTOMPARAMS object.
	w32_platformInit,		///< FFT_ONCREATE event.
	NULL,					///< FFT_ONEXIT event.
	w32_fgetc,				///< Custom fgetc (input) handler.
	w32_getTicks,			///< FFT_GETTICKS handler.
	w32_getTickRate,		///< FFT_GETTICKRATE handler.
	w32_getConsoleWidth,	///< FFT_GETCONSOLEWIDTH handler.
	w32_getConsoleHeight,	///< FFT_GETCONSOLEHEIGHT handler.
	w32_setConsoleColour,	///< FFT_SETCONSOLECOLOUR handler.
	w32_createBgThread,		///< FFT_CREATEBGTHREAD	agent.
	NULL,					///< Filesystem autocomplete agent.
};

FFT_PLATFORMSPEC *w32_getSpec() {
	return &g_oPlatformSpecification;
}
